home *** CD-ROM | disk | FTP | other *** search
/ 3D GFX / 3D GFX.iso / amiutils / i_l / irit5 / cagd_lib / cagdsmrg.c < prev    next >
C/C++ Source or Header  |  1995-12-30  |  13KB  |  354 lines

  1. /******************************************************************************
  2. * CagdCMrg.c - Surface/Surface merging routine.                      *
  3. *******************************************************************************
  4. * Written by Gershon Elber, Sep 92.                          *
  5. ******************************************************************************/
  6.  
  7. #include "cagd_loc.h"
  8.  
  9. static void InterpolateLinearSeg(CagdRType *V1,
  10.                  CagdRType *V2,
  11.                  int Len,
  12.                  int Step);
  13.  
  14. /*****************************************************************************
  15. * DESCRIPTION:                                                               M
  16. * Merges two surfaces in the requested direction Dir.                 M
  17. *  If SameEdge, it is assumed last edge of Srf1 is identical to first edge   M
  18. * of Srf2 and one row is dropped from new mesh. Otherwise a ruled surface is M
  19. * fit between the two edges.                                                 M
  20. *                                                                            *
  21. * PARAMETERS:                                                                M
  22. *   Srf1:                 To connect to Srf1's starting boundary at its end. M
  23. *   Srf2:                 To connect to Srf2's end boundary at its start.    M
  24. *   Dir:                  Direction the merge should take place. Either U    M
  25. *                         or V.                             M
  26. *   SameEdge:             If the two surfaces sharea common edge.            M
  27. *   InterpolateDiscont:   If TRUE, linearly interpolate discontinuity.       M
  28. *                                                                            *
  29. * RETURN VALUE:                                                              M
  30. *   CagdSrfStruct *:     The merged surface.                                 M
  31. *                                                                            M
  32. * KEYWORDS:                                                                  M
  33. *   CagdMergeSrfSrf, merge                                                   M
  34. *****************************************************************************/
  35. CagdSrfStruct *CagdMergeSrfSrf(CagdSrfStruct *Srf1,
  36.                    CagdSrfStruct *Srf2,
  37.                    CagdSrfDirType Dir,
  38.                    CagdBType SameEdge,
  39.                    int InterpolateDiscont)
  40. {
  41.     CagdBType IsNotRational;
  42.     int i, j, UOrder, VOrder, ULen1, VLen1, ULen2, VLen2, MaxCoord, Length;
  43.     CagdRType **Points1, **Points2, **Points;
  44.     CagdPointType SrfPType;
  45.     CagdSrfStruct *Srf;
  46.  
  47.     if (CAGD_IS_PERIODIC_SRF(Srf1) || CAGD_IS_PERIODIC_SRF(Srf2)) {
  48.     Srf1 = CnvrtPeriodic2FloatSrf(Srf1);
  49.     Srf2 = CnvrtPeriodic2FloatSrf(Srf2);
  50.     }
  51.     else {
  52.     /* To make surfaces compatible: */
  53.     Srf1 = CagdSrfCopy(Srf1);
  54.     Srf2 = CagdSrfCopy(Srf2);
  55.     }
  56.  
  57.     switch (Dir) {
  58.     case CAGD_CONST_U_DIR:
  59.     case CAGD_CONST_V_DIR:
  60.         if (!CagdMakeSrfsCompatible(&Srf1, &Srf2, TRUE, TRUE,
  61.                     Dir == CAGD_CONST_V_DIR,
  62.                     Dir == CAGD_CONST_U_DIR))
  63.         CAGD_FATAL_ERROR(CAGD_ERR_SRF_FAIL_CMPT);
  64.         break;
  65.     default:
  66.         CAGD_FATAL_ERROR(CAGD_ERR_DIR_NOT_CONST_UV);
  67.         break;
  68.     }
  69.  
  70.     /* Verify surface geometric types. */
  71.     switch (Srf1 -> GType) {
  72.     case CAGD_SBEZIER_TYPE:
  73.         Srf = CnvrtBezier2BsplineSrf(Srf1);
  74.         CagdSrfFree(Srf1);
  75.         Srf1 = Srf;
  76.         Srf = CnvrtBezier2BsplineSrf(Srf2);
  77.         CagdSrfFree(Srf2);
  78.         Srf2 = Srf;
  79.         break;
  80.     case CAGD_SBSPLINE_TYPE:
  81.         break;
  82.     case CAGD_SPOWER_TYPE:
  83.         CAGD_FATAL_ERROR(CAGD_ERR_POWER_NO_SUPPORT);
  84.         break;
  85.     default:
  86.         CAGD_FATAL_ERROR(CAGD_ERR_UNDEF_SRF);
  87.         break;
  88.     }
  89.  
  90.     UOrder = Srf1 -> UOrder;
  91.     VOrder = Srf1 -> VOrder;
  92.     ULen1 = Srf1 -> ULength;
  93.     VLen1 = Srf1 -> VLength;
  94.     ULen2 = Srf2 -> ULength;
  95.     VLen2 = Srf2 -> VLength;
  96.     Points1 = Srf1 -> Points;
  97.     Points2 = Srf2 -> Points;
  98.     IsNotRational = !CAGD_IS_RATIONAL_SRF(Srf1);
  99.     MaxCoord = CAGD_NUM_OF_PT_COORD(Srf1 -> PType),
  100.     SrfPType = CAGD_MAKE_PT_TYPE(!IsNotRational, MaxCoord);
  101.  
  102.     switch (Dir) {
  103.     case CAGD_CONST_U_DIR:
  104.         Length = SameEdge ? ULen1 + ULen2 - 1
  105.                   : InterpolateDiscont ? ULen1 + ULen2 + UOrder - 2
  106.                            : ULen1 + ULen2;
  107.  
  108.         Srf = BspSrfNew(Length, VLen1, UOrder, VOrder, SrfPType);
  109.  
  110.         /* Update knot vectors. We assume open end condition here... */
  111.         CAGD_GEN_COPY(Srf -> UKnotVector, Srf1 -> UKnotVector,
  112.               (ULen1 + UOrder - 1) * sizeof(CagdRType));
  113.         CAGD_GEN_COPY(Srf -> VKnotVector, Srf1 -> VKnotVector,
  114.               (VLen1 + VOrder) * sizeof(CagdRType));
  115.  
  116.         if (SameEdge) {
  117.         /* Copy kv of second surface immediately after. */
  118.         CAGD_GEN_COPY(&Srf -> UKnotVector[ULen1 + UOrder - 1],
  119.                   &Srf2 -> UKnotVector[UOrder],
  120.                   ULen2 * sizeof(CagdRType));
  121.         BspKnotAffineTrans(&Srf -> UKnotVector[ULen1 + UOrder - 1],
  122.                    ULen2,
  123.                    Srf -> UKnotVector[ULen1 + UOrder - 2] -
  124.                    Srf2 -> UKnotVector[0],
  125.                    1.0);
  126.         }
  127.         else if (InterpolateDiscont) {
  128.         /* Copy kv of second surface order after. */
  129.         CAGD_GEN_COPY(&Srf -> UKnotVector[ULen1 + UOrder - 1],
  130.                   &Srf2 -> UKnotVector[1],
  131.                   (ULen2 + UOrder - 1) * sizeof(CagdRType));
  132.         BspKnotAffineTrans(&Srf -> UKnotVector[ULen1 + UOrder - 1],
  133.                    ULen2 + UOrder - 1,
  134.                    Srf -> UKnotVector[ULen1 + UOrder - 2] -
  135.                    Srf -> UKnotVector[ULen1 + UOrder - 1] + 1.0,
  136.                    1.0);
  137.         }
  138.         else {
  139.         CAGD_GEN_COPY(&Srf -> UKnotVector[ULen1 + UOrder - 1],
  140.                   &Srf2 -> UKnotVector[UOrder - 1],
  141.                   (ULen2 + 1) * sizeof(CagdRType));
  142.         BspKnotAffineTrans(&Srf -> UKnotVector[ULen1 + UOrder - 1],
  143.                    ULen2 + 1,
  144.                    Srf1 -> UKnotVector[ULen1 + UOrder - 1] -
  145.                    Srf -> UKnotVector[ULen1 + UOrder - 1],
  146.                    1.0);
  147.         }
  148.  
  149.         Points = Srf -> Points;
  150.  
  151.         for (i = 0; i < VLen1; i++) {
  152.         for (j = IsNotRational; j <= MaxCoord; j++) {
  153.             CAGD_GEN_COPY(&Points[j][CAGD_MESH_UV(Srf, 0, i)],
  154.                   &Points1[j][CAGD_MESH_UV(Srf1, 0, i)],
  155.                   ULen1 * sizeof(CagdRType));
  156.             if (SameEdge) {
  157.             /* Copy row of second surface immediately after. */
  158.             CAGD_GEN_COPY(
  159.                 &Points[j][CAGD_MESH_UV(Srf, ULen1 - 1, i)],
  160.                 &Points2[j][CAGD_MESH_UV(Srf2, 0, i)],
  161.                 ULen2 * sizeof(CagdRType));
  162.             }
  163.             else if (InterpolateDiscont) {
  164.             /* Copy row of 2nd srf order after and lin. interp. */
  165.             CAGD_GEN_COPY(
  166.                 &Points[j][CAGD_MESH_UV(Srf, ULen1 + UOrder - 2, i)],
  167.                 &Points2[j][CAGD_MESH_UV(Srf2, 0, i)],
  168.                 ULen2 * sizeof(CagdRType));
  169.             InterpolateLinearSeg(
  170.                 &Points[j][CAGD_MESH_UV(Srf, ULen1 - 1, i)],
  171.                 &Points[j][CAGD_MESH_UV(Srf, ULen1 + UOrder - 2, i)],
  172.                 UOrder, 1);
  173.             }
  174.             else {
  175.             /* Copy row of 2nd srf order after and lin. interp. */
  176.             CAGD_GEN_COPY(
  177.                 &Points[j][CAGD_MESH_UV(Srf, ULen1, i)],
  178.                 &Points2[j][CAGD_MESH_UV(Srf2, 0, i)],
  179.                 ULen2 * sizeof(CagdRType));
  180.             }
  181.         }
  182.         }
  183.         break;
  184.     case CAGD_CONST_V_DIR:
  185.         Length = SameEdge ? VLen1 + VLen2 - 1
  186.                   : InterpolateDiscont ? VLen1 + VLen2 + VOrder - 2
  187.                            : VLen1 + VLen2;
  188.  
  189.         Srf = BspSrfNew(ULen1, Length, UOrder, VOrder, SrfPType);
  190.  
  191.         /* Update knot vectors. We assume open end condition here... */
  192.         CAGD_GEN_COPY(Srf -> UKnotVector, Srf1 -> UKnotVector,
  193.               (ULen1 + UOrder) * sizeof(CagdRType));
  194.         CAGD_GEN_COPY(Srf -> VKnotVector, Srf1 -> VKnotVector,
  195.               (VLen1 + VOrder - 1) * sizeof(CagdRType));
  196.  
  197.         if (SameEdge) {
  198.         /* Copy kv of second surface immediately after. */
  199.         CAGD_GEN_COPY(&Srf -> VKnotVector[VLen1 + VOrder - 1],
  200.                   &Srf2 -> VKnotVector[VOrder],
  201.                   VLen2 * sizeof(CagdRType));
  202.         BspKnotAffineTrans(&Srf -> VKnotVector[VLen1 + VOrder - 1],
  203.                    VLen2,
  204.                    Srf -> VKnotVector[VLen1 + VOrder - 2] -
  205.                    Srf2 -> VKnotVector[0],
  206.                    1.0);
  207.         }
  208.         else if (InterpolateDiscont) {
  209.         /* Copy kv of second surface order after. */
  210.         CAGD_GEN_COPY(&Srf -> VKnotVector[VLen1 + VOrder - 1],
  211.                   &Srf2 -> VKnotVector[1],
  212.                   (VLen2 + VOrder - 1) * sizeof(CagdRType));
  213.         BspKnotAffineTrans(&Srf -> VKnotVector[VLen1 + VOrder - 1],
  214.                    VLen2 + VOrder - 1,
  215.                    Srf -> VKnotVector[VLen1 + VOrder - 2] -
  216.                    Srf -> VKnotVector[VLen1 + VOrder - 1] + 1.0,
  217.                    1.0);
  218.         }
  219.             else {
  220.         CAGD_GEN_COPY(&Srf -> VKnotVector[VLen1 + VOrder - 1],
  221.                   &Srf2 -> VKnotVector[VOrder - 1],
  222.                   (VLen2 + 1) * sizeof(CagdRType));
  223.         BspKnotAffineTrans(&Srf -> VKnotVector[VLen1 + VOrder - 1],
  224.                    VLen2 + 1,
  225.                    Srf1 -> VKnotVector[VLen1 + VOrder - 1] -
  226.                    Srf -> VKnotVector[VLen1 + VOrder - 1],
  227.                    1.0);
  228.         }
  229.  
  230.         Points = Srf -> Points;
  231.  
  232.         for (i = 0; i < ULen1; i++) {
  233.         for (j = IsNotRational; j <= MaxCoord; j++) {
  234.             CAGD_GEN_COPY_STEP(&Points[j][CAGD_MESH_UV(Srf, i, 0)],
  235.                        &Points1[j][CAGD_MESH_UV(Srf1, i, 0)],
  236.                        VLen1, ULen1, ULen1, CagdRType);
  237.             if (SameEdge) {
  238.             /* Copy col of second surface immediately after. */
  239.             CAGD_GEN_COPY_STEP(
  240.                 &Points[j][CAGD_MESH_UV(Srf, i, VLen1 - 1)],
  241.                 &Points2[j][CAGD_MESH_UV(Srf2, i, 0)],
  242.                 VLen2, ULen1, ULen1, CagdRType);
  243.             }
  244.             else if (InterpolateDiscont) {
  245.             /* Copy col of 2nd srf order after and lin. interp. */
  246.             CAGD_GEN_COPY_STEP(
  247.                 &Points[j][CAGD_MESH_UV(Srf, i, VLen1 + VOrder - 2)],
  248.                 &Points2[j][CAGD_MESH_UV(Srf2, i, 0)],
  249.                 VLen2, ULen1, ULen1, CagdRType);
  250.             InterpolateLinearSeg(
  251.                 &Points[j][CAGD_MESH_UV(Srf, i, VLen1 - 1)],
  252.                 &Points[j][CAGD_MESH_UV(Srf, i, VLen1 + VOrder - 2)],
  253.                 VOrder, ULen1);
  254.             }
  255.             else {
  256.             /* Copy col of 2nd srf order after and lin. interp. */
  257.             CAGD_GEN_COPY_STEP(
  258.                 &Points[j][CAGD_MESH_UV(Srf, i, VLen1)],
  259.                 &Points2[j][CAGD_MESH_UV(Srf2, i, 0)],
  260.                 VLen2, ULen1, ULen1, CagdRType);
  261.             }
  262.         }
  263.         }
  264.         break;
  265.     default:
  266.         Srf = NULL;
  267.         CAGD_FATAL_ERROR(CAGD_ERR_DIR_NOT_CONST_UV);
  268.         break;
  269.     }
  270.  
  271.     CagdSrfFree(Srf1);
  272.     CagdSrfFree(Srf2);
  273.  
  274.     return Srf;
  275. }
  276.  
  277. /*****************************************************************************
  278. * DESCRIPTION:                                                               M
  279. * Merges a list of surfaces by connecting the end of one surface to the      M
  280. * begining of the next. See also CagdMergeSrfSrf.                            M
  281. *                                                                            *
  282. * PARAMETERS:                                                                M
  283. *   SrfList:              To connect into one surface.                       M
  284. *   Dir:                  Direction the merge should take place. Either U    M
  285. *                         or V.                             M
  286. *   SameEdge:             If the two surfaces sharea common edge.            M
  287. *   InterpolateDiscont:   If TRUE, linearly interpolate discontinuity.       M
  288. *                                                                            *
  289. * RETURN VALUE:                                                              M
  290. *   CagdSrfStruct *:     The merged surface.                                 M
  291. *                                                                            *
  292. * KEYWORDS:                                                                  M
  293. *   CagdMergeSrfList, merge                                                  M
  294. *****************************************************************************/
  295. CagdSrfStruct *CagdMergeSrfList(CagdSrfStruct *SrfList,
  296.                 CagdSrfDirType Dir,
  297.                 CagdBType SameEdge,
  298.                 int InterpolateDiscont)
  299. {
  300.     if (SrfList != NULL && SrfList -> Pnext != NULL) {
  301.     CagdSrfStruct
  302.         *MergedSrf = CagdSrfCopy(SrfList);
  303.  
  304.     for (SrfList = SrfList -> Pnext;
  305.          SrfList != NULL;
  306.          SrfList = SrfList -> Pnext) {
  307.         CagdSrfStruct
  308.         *TmpSrf = CagdMergeSrfSrf(MergedSrf, SrfList, Dir, SameEdge,
  309.                       InterpolateDiscont);
  310.  
  311.         CagdSrfFree(MergedSrf);
  312.         MergedSrf = TmpSrf;
  313.     }
  314.     return MergedSrf;
  315.     }
  316.     else
  317.     return SrfList ? CagdSrfCopy(SrfList) : NULL;
  318. }
  319.  
  320. /*****************************************************************************
  321. * DESCRIPTION:                                                               *
  322. * Linearly interpolates between V1 and V2 values Len times (Len includes V1  *
  323. * and V2) and step the array using Step.                     *
  324. *                                                                            *
  325. *                                                                            *
  326. *                                                                            *
  327. * PARAMETERS:                                                                *
  328. *   V1:       First coefficient to linearly interpolate.                     *
  329. *   V2:       Seoncd coefficient to linearly interpolate.                    *
  330. *   Len:      Of coefficients to linearly interpolate from V1 to V2.         *
  331. *   Step:     To take while interpolating.                                   *
  332. *                                                                            *
  333. * RETURN VALUE:                                                              *
  334. *   void                                                                     *
  335. *****************************************************************************/
  336. static void InterpolateLinearSeg(CagdRType *V1,
  337.                  CagdRType *V2,
  338.                  int Len,
  339.                  int Step)
  340. {
  341.     int i;
  342.     CagdRType
  343.     *V = V1 + Step;
  344.  
  345.     if (Len-- <= 2)
  346.     return;                     /* No middle points to interp. */
  347.  
  348.     for (i = 1; i < Len; i++) {
  349.     *V = (i * (*V2) + (Len - i) * (*V1)) / Len;
  350.  
  351.     V += Step;
  352.     }
  353. }
  354.